package edu.mtu.citizenscience.cs.sdk.json;

import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import edu.mtu.citizenscience.cs.sdk.ServerRequest;
/**
 * @author Corbin Uselton <corbinu@cwuselto@mtu.edu>
 * @copyright (c) 2012 MichiganTech <http://www.mtu.edu>
 * @since 1.0
 * 
 * Request to make to the CitSci server
 */
public class Request<E> {
	// action on the API resource
	private String action = "GET";
	// response and request format json or xml
	private String format = "json";
	// fields to return if getting resource
	private String[] fields;
	// limit of the number of responses
	private int limit = 10;
	// the offset for paginating responses
	private int offset = 0;
	// the id of the resource
	private int id = -1;
	// the api key
	private String key;
	// to alaways return a HTTP status code of 200
	private boolean always200 = true;
	// the request payload
	private E payload;
	// additional request params
	private Map<String, Object> params = new HashMap<String, Object>();
	
	/**
	 * Create the Request
	 * 
	 * @param   void
	 * @return	void
	 */
	public Request() {  }
	
	/**
	 * Create the Request
	 * 
	 * @param   action - String - the request action
	 * @return	void
	 */
	public Request(String action)
	{
		this.action = action;
	}
	
	/**
	 * Create the Request
	 * 
	 * @param   action - String - the request action
	 * @param	payload - E - the request playload
	 * @return	void
	 */
	public Request(String action, E payload)
	{
		this.action = action;
		this.payload = payload;
	}
	
	/**
	 * Create the Request
	 * 
	 * @param   action - String - the request action
	 * @param	id - int - the resource id
	 * @return	void
	 */
	public Request(String action, int id)
	{
		this.action = action;
		this.id = id;
	}
	
	/**
	 * Create the Request
	 * 
	 * @param   action - String - the request action
	 * @param	id - int - the resource id
	 * @param	payload - E - the request playload
	 * @return	void
	 */
	public Request(String action, int id, E payload)
	{
		this.action = action;
		this.id = id;
		this.payload = payload;
	}
	
	/**
	 * Get the request action
	 * 
	 * @param   void
	 * @return	String - request action
	 */
	public String getAction() 
	{
		return action;
	}
	
	/**
	 * Set the request action
	 * 
	 * @param   action - String - request action
	 * @return	void
	 */
	public void setAction(String action) 
	{
		this.action = action;
	}
	
	/**
	 * Get the request format
	 * 
	 * @param   void
	 * @return	String - request format
	 */
	public String getFormat() 
	{
		return format;
	}
	
	/**
	 * Set the request format
	 * 
	 * @param   format - String - request format
	 * @return	void
	 */
	public void setFormat(String format) 
	{
		this.format = format;
	}
	
	/**
	 * Get the request fields
	 * 
	 * @param   void
	 * @return	String[] - request fields
	 */
	public String[] getFields() 
	{
		return fields;
	}
	
	/**
	 * Set the request fields
	 * 
	 * @param   fields - String[] - request fields
	 * @return	void
	 */
	public void setFields(String[] fields) 
	{
		this.fields = fields;
	}
	
	/**
	 * Get the request limit
	 * 
	 * @param   void
	 * @return	int - the request limit
	 */
	public int getLimit() 
	{
		return limit;
	}
	
	/**
	 * Set the request limit
	 * 
	 * @param   limit - int - the request limit
	 * @return	void
	 */
	public void setLimit(int limit) 
	{
		this.limit = limit;
	}
	
	/**
	 * Get the request offset
	 * 
	 * @param   void
	 * @return	int - request offset
	 */
	public int getOffset() 
	{
		return offset;
	}
	
	/**
	 * Set the request offset
	 * 
	 * @param   offset - int - request offset
	 * @return	void
	 */
	public void setOffset(int offset) 
	{
		this.offset = offset;
	}
	
	/**
	 * Get the request id
	 * 
	 * @param   void
	 * @return	int - the request id
	 */
	public int getId() 
	{
		return id;
	}
	
	/**
	 * Set the request id
	 * 
	 * @param   id - int - the request id
	 * @return	void
	 */
	public void setId(int id) 
	{
		this.id = id;
	}
	
	/**
	 * Get the request API key
	 * 
	 * @param   void
	 * @return	String - request API key
	 */
	public String getKey() 
	{
		return key;
	}
	
	/**
	 * Set the request API key
	 * 
	 * @param   key - String - request API key
	 * @return	void
	 */
	public void setKey(String key) 
	{
		this.key = key;
	}
	
	/**
	 * Check the request is always 200
	 * 
	 * @param   void
	 * @return	boolean - request always 200
	 */
	public boolean isAlways200() 
	{
		return always200;
	}
	
	/**
	 * Set the request is always 200
	 * 
	 * @param   always200 - boolean - request always 200
	 * @return	void
	 */
	public void setAlways200(boolean always200) 
	{
		this.always200 = always200;
	}
	
	/**
	 * Get the request payload
	 * 
	 * @param   void
	 * @return	E - request payload
	 */
	public E getPayload() 
	{
		return payload;
	}
	
	/**
	 * Set the request payload
	 * 
	 * @param   payload - E - request payload
	 * @return	void
	 */
	public void setPayload(E payload) 
	{
		this.payload = payload;
	}
	
	/**
	 * Add param to the request
	 * 
	 * @param   name - String - param name
	 * @param   value - Object - param value
	 * @return	void
	 */
	public void addParam(String name, Object value) 
	{
		this.params.put(name, value);
	}
	
	/**
	 * Get the request params
	 * 
	 * @param   void
	 * @return	Map<String, Object> - map of request params
	 */
	public Map<String, Object> getParams()
	{
		// add request fields
		this.params.put("fields", this.getFields());
		// add request API key
		this.params.put("key", ServerRequest.API_KEY);
		// add request limit
		this.params.put("limit", this.getLimit());
		// add request offset
		this.params.put("offset", this.getOffset());
		// add request always 200
		this.params.put("always200", this.isAlways200());
		try 
		{
			// add request payload
			this.params.put("payload", new ObjectMapper().writeValueAsString(this.getPayload()));
		} 
		catch (JsonProcessingException e) 
		{
			// happens if the there is a problem converting the payload to JSON
			e.printStackTrace();
		}
		
		// return the request params
		return this.params;
	}
}
